/**
 * 
 */
package algo.LocalSearch.vrp;

import algo.LocalSearch.*;

/**
 * @author dungpq
 *
 */
public interface IFunctionVRP {
	double getValue();
	
	/*
	 * query the evaluation of different moves 
	 */
	
	// move of type a [Groer et al., 2010]
	// move customer x to from route of x to route of y; insert x into the position between y and next[y]
	// x and y are not depot
	// remove (prev[x],x), (x, next[x]), (y,next[y])
	// insert (prev[x], next[x]), (y,x), (x, next[y])
	double evaluateOnePointMove(VarIntLS x, VarIntLS y);
	
	// move of type b [Groer et al., 2010]
	// x and y are on the same route and are not depots, y locates before x on the route
	// remove (prev[x],x) and (x,next[x]) and (prev[y], y) and (y, next(y)
	// insert (x,next[y]) and (prev[y],x) and (prev[x],y) and (y, next[x])
	double evaluateTwoPointsMove(VarIntLS x, VarIntLS y);
	
	// move of type c [Groer et al., 2010]
	// x and y are on different routes and are not depots
	// remove (x,next[x]) and (y,next[y])
	// insert (x,y) and (next[x],next(y))
	double evaluateTwoOptMove1(VarIntLS x, VarIntLS y);
	// insert (y,x) and (next[x],next(y))
	double evaluateTwoOptMove2(VarIntLS x, VarIntLS y);
	// insert (x,y) and (next[y],next(x))
	double evaluateTwoOptMove3(VarIntLS x, VarIntLS y);
	// insert (y,x) and (next[y],next(x))
	double evaluateTwoOptMove4(VarIntLS x, VarIntLS y);
	// insert (x,next[y]) and (y,next[x])
	double evaluateTwoOptMove5(VarIntLS x, VarIntLS y);
	// insert (next[y],x) and (y,next[x])
	double evaluateTwoOptMove6(VarIntLS x, VarIntLS y);
	// insert (x,next[y]) and (next[x],y)
	double evaluateTwoOptMove7(VarIntLS x, VarIntLS y);
	// insert (next[y],x) and (next[x],y)
	double evaluateTwoOptMove8(VarIntLS x, VarIntLS y);

	// move of type d [Groer et al., 2010]
	// move the sequence <x,next[x]...> of length len to the route containing y
	// last[x] = the last customer of the sequence of length length starting from x
	// remove (prev[x],x) and (last[x],next[last[x]], and (y,next[y])
	
	// add (y, last[x]) and (x, next[y]) and (prev[x], next[last[x]])
	double evaluateOrOptMove1(VarIntLS x, int len, VarIntLS z);
	// add (y, x) and (last[x], next[y]) and (prev[x], next[last[x]])
	double evaluateOrOptMove2(VarIntLS x, int len, VarIntLS z);
		
		
	// move of type e [Groer et al., 2010]
	// x, y, z are on the same route in that order (x is before y, y is before z)
	// remove (x, next[x]), (y, next[y]), and (z, next[z])
	// insert (x,z) and (next[y], next[x]) and(y, next[z])
	double evaluateThreeOptMove1(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (z,x) and (next[x], next[y]) and(next[z],y)
	double evaluateThreeOptMove2(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (x,y) and (next[x], z) and(next[y], next[z])
	double evaluateThreeOptMove3(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (y,x) and (z,next[x]) and(next[z], next[y])
	double evaluateThreeOptMove4(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (x,next[y]) and (z,next[x]) and(y, next[z])
	double evaluateThreeOptMove5(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (next[y],x) and (next[x],z) and(next[z],y)
	double evaluateThreeOptMove6(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (x,next[y]) and (z,y) and(next[x], next[z])
	double evaluateThreeOptMove7(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (next[y],x) and (y,z) and(next[z], next[x])
	double evaluateThreeOptMove8(VarIntLS x, VarIntLS y, VarIntLS z);
		

	
	// move of type g [Groer et al., 2010]
	// x1 and y1 are on the same route, x1 is beore y1
	// x2 and y2 are on the same route, x2 is before y2
	// remove (x1,next[x1]) and (y1, next[y1])
	// remove (x2, next[x2]) and (y2, next[y2])
	// insert (x1, next[x2]) and (y2, next[y1])
	// insert (x2, next[x1]) and (y1, next[y2])
	double evaluateCrossExchangeMove(VarIntLS x1, VarIntLS y1, VarIntLS x2, VarIntLS y2);
	
	
	/*
	 * Perform moves and propagate impact
	 */
	
	// move of type a [Groer et al., 2010]
	// move customer x to from route of x to route of y; insert x into the position between y and next[y]
	// x and y are nto depot
	double propagateOnePointMove(VarIntLS x, VarIntLS y);
	
	// move of type b [Groer et al., 2010]
	// x and y are on the same route and are not depots, y locates before x on the route
	// remove (prev[x],x) and (x,next[x]) and (prev[y], y) and (y, next(y)
	// insert (x,next[y]) and (prev[y],x) and (prev[x],y) and (y, next[x])
	double propagateTwoPointsMove(VarIntLS x, VarIntLS y);
	
	// move of type c [Groer et al., 2010]
	// x and y are on different routes and are not depots
	// remove (x,next[x]) and (y,next[y])
	// insert (x,y) and (next[x],next(y))
	double propagateTwoOptMove1(VarIntLS x, VarIntLS y);
	// insert (y,x) and (next[x],next(y))
	double propagateTwoOptMove2(VarIntLS x, VarIntLS y);
	// insert (x,y) and (next[y],next(x))
	double propagateTwoOptMove3(VarIntLS x, VarIntLS y);
	// insert (y,x) and (next[y],next(x))
	double propagateTwoOptMove4(VarIntLS x, VarIntLS y);
	// insert (x,next[y]) and (y,next[x])
	double propagateTwoOptMove5(VarIntLS x, VarIntLS y);
	// insert (next[y],x) and (y,next[x])
	double propagateTwoOptMove6(VarIntLS x, VarIntLS y);
	// insert (x,next[y]) and (next[x],y)
	double propagateTwoOptMove7(VarIntLS x, VarIntLS y);
	// insert (next[y],x) and (next[x],y)
	double propagateTwoOptMove8(VarIntLS x, VarIntLS y);

	// move of type d [Groer et al., 2010]
	// move the sequence <x,next[x]...> of length len to the route containing y
	// last[x] = the last customer of the sequence of length length starting from x
	// remove (prev[x],x) and (last[x],next[last[x]], and (y,next[y])
	
	// add (y, last[x]) and (x, next[y]) and (prev[x], next[last[x]])
	double propagateOrOptMove1(VarIntLS x, int len, VarIntLS z);
	// add (y, x) and (last[x], next[y]) and (prev[x], next[last[x]])
	double propagateOrOptMove2(VarIntLS x, int len, VarIntLS z);
		
		
	// move of type e [Groer et al., 2010]
	// x, y, z are on the same route in that order (x is before y, y is before z)
	// remove (x, next[x]), (y, next[y]), and (z, next[z])
	// insert (x,z) and (next[y], next[x]) and(y, next[z])
	double propagateThreeOptMove1(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (z,x) and (next[x], next[y]) and(next[z],y)
	double propagateThreeOptMove2(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (x,y) and (next[x], z) and(next[y], next[z])
	double propagateThreeOptMove3(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (y,x) and (z,next[x]) and(next[z], next[y])
	double propagateThreeOptMove4(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (x,next[y]) and (z,next[x]) and(y, next[z])
	double propagateThreeOptMove5(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (next[y],x) and (next[x],z) and(next[z],y)
	double propagateThreeOptMove6(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (x,next[y]) and (z,y) and(next[x], next[z])
	double propagateThreeOptMove7(VarIntLS x, VarIntLS y, VarIntLS z);
	// insert (next[y],x) and (y,z) and(next[z], next[x])
	double propagateThreeOptMove8(VarIntLS x, VarIntLS y, VarIntLS z);
		

	
	// move of type g [Groer et al., 2010]
	// x1 and y1 are on the same route, x1 is beore y1
	// x2 and y2 are on the same route, x2 is before y2
	// remove (x1,next[x1]) and (y1, next[y1])
	// remove (x2, next[x2]) and (y2, next[y2])
	// insert (x1, next[x2]) and (y2, next[y1])
	// insert (x2, next[x1]) and (y1, next[y2])
	double propagateCrossExchangeMove(VarIntLS x1, VarIntLS y1, VarIntLS x2, VarIntLS y2);

}
